/**
 * Copyright (c) 2014-2016 www.nryuncang.com. All Rights Reserved.
 */
package com.topisv.tms.web.orderInput;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONObject;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.shiro.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.topisv.tms.entity.CustomerLead;
import com.topisv.tms.entity.JSONParam;
import com.topisv.tms.entity.work.WorkOrder;
import com.topisv.tms.service.CustomersService;
import com.topisv.tms.service.LogisticsCompanyService;
import com.topisv.tms.service.account.ShiroDbRealm.ShiroUser;
import com.topisv.tms.service.work.WorkOrderService;
import com.topisv.tms.tools.DataTablesUtils;
import com.topisv.tms.utils.DateUtils;
import com.topisv.tms.utils.excel.ExcelImportUtil;
import com.topisv.tms.web.base.BaseDataTableController;


/**
 * 快递单资料导入
 * 根据订单好把线下的文件（包含快递单号的）导入系统订单表中，之后....(其他操作)
 * @author <a href=mailto:libin@nryuncang.com>libin</a>
 * @version 1.0.0
 */

@Controller
@RequestMapping(value = "/v2/expressNoInput")
public class ExpressNoInputController extends BaseDataTableController{
    //TODO  Logger
    private static final Logger log = LoggerFactory.getLogger(ExpressNoInputController.class);

    @Autowired
    private CustomersService customersService;
    @Autowired
    private WorkOrderService workOrderService;
    @Autowired
    private LogisticsCompanyService logisticsCompanyService;
    
    /**
     * 导向初始化页面
     * @param
     * @return
     * @throws
     * @author <a href=mailto:libin@nryuncang.com>libin</a>
     * @version 1.0.0
     */
    @RequestMapping(value = "init")
    public String init(ServletRequest request, HttpServletResponse response, Model model) {
        
        fillSelectValue(model, null);
        model.addAttribute("logisticsList", logisticsCompanyService.findAll());
        
        return "expressNoInput/billList";
    }
    
    /**
     * 加载数据
     * @param
     * @return
     * @throws
     * @author <a href=mailto:libin@nryuncang.com>libin</a>
     * @version 1.0.0
     */
    @RequestMapping(value = "/loadData", method = RequestMethod.POST)
    public void loadData(@RequestBody JSONParam[] paramJson, HttpServletRequest request, HttpServletResponse response)throws Exception{
        try {
            PrintWriter out = response.getWriter();
            JSONObject json = new JSONObject();
            Page<WorkOrder> page = null;
            
            Map<String, Object> param = new HashMap<String, Object>();
            ShiroUser shiroUser = (ShiroUser)SecurityUtils.getSubject().getPrincipal();
            Map<String, String> paramMap = DataTablesUtils.convertToMap(paramJson);// 客户端参数
            int start = Integer.parseInt(paramMap.get("iDisplayStart"));
            int length = Integer.parseInt(paramMap.get("iDisplayLength"));
            
            if (StringUtils.isEmpty(paramMap.get("customerCode"))) { // 如果商家编码为空，赋予默认权限值
                String customerCodes = this.customersService.loadCustomerByAuthority(shiroUser.jobuuid);
                param.put("customerCodes", customerCodes);
            } else {
                param.put("customerCode", paramMap.get("customerCode"));
            }
           
            if (StringUtils.isNotEmpty(paramMap.get("dataRange"))) {
                Map<String, Date> dataMap = DateUtils.getDateRange(paramMap.get("dataRange"));
                param.put("inputFromDate", dataMap.get("fromDate"));
                param.put("inputToDate", dataMap.get("toDate"));
            }
            
            param.put("warehouseCode", paramMap.get("warehouseCode"));
            param.put("cancelStatus", "ok");
            param.put("status", paramMap.get("status"));
            param.put("ordernoOrExpressno", paramMap.get("orderno"));
            param.put("workStatus", paramMap.get("status"));
            param.put("companyCode", paramMap.get("cacode"));
            param.put("batchCode", paramMap.get("batchCode"));
            param.put("taskCode", paramMap.get("taskCode"));
            param.put("expressBuiltType", "1");
            param.put("expressNo", paramMap.get("expressNo"));
            
            // 查询
            int curPage = (start / length) + 1;
            page = this.workOrderService.loadPageOrder(param, curPage, length);
            List<WorkOrder> orderList = page.getContent();
            
            // 封装查询结果
            json.put("aaData", orderList);
            json.put("sEcho", paramMap.get("sEcho"));
            json.put("iTotalRecords", page.getTotalElements());
            json.put("iTotalDisplayRecords", page.getTotalElements());
            
            out.print(json);
            
        } catch (Exception e) {
            log.error("搜索查询异常", e);
        }
    }
    
    /**
     * 把选择的单据标记为已打印
     * @param 
     * @return 
     * @throws 
     * @author <a href=mailto:libin@nryuncang.com>libin</a>
     * @version 1.0.0
     */
    @RequestMapping(value = "markPrintred")
    public void ajaxMarkPrintred(@RequestParam(value = "ids") String ids, HttpServletResponse response) {
        JSONObject json = new JSONObject();
        PrintWriter out = null;
        try {
            out = response.getWriter();
            ShiroUser shiroUser = (ShiroUser)SecurityUtils.getSubject().getPrincipal();
            
            log.info("标记为已打印的id {}",ids);
            int n = workOrderService.markWorkOrderPrinted(ids);
            int m = workOrderService.markWorkTaskPrinted(ids);
            workOrderService.addWorkOrderPrintLog(ids, shiroUser);
            log.info("标记为已打印的结果：workorder表的个数 {},worktask的个数 {}",n,m);
            json.put("content", "设置成功");
            json.put("status", "1");
            out.print(json.toString());

        } catch (Exception e) {
            json.put("status", "0");
            json.put("content", e.getMessage());
            if (null != out)
                out.print(json.toString());
        }
    }
    
    /**
     * 运单号导入作业订单
     * @param 
     * @return 
     * @throws 
     * @author <a href=mailto:libin@nryuncang.com>libin</a>
     * @version 1.0.0
     */
    @SuppressWarnings("unchecked")
    @RequestMapping(value = "exprssNoInputToWorkOrder/{customerCode}/{warehouseCode}/{companyCode}")
    public String exprssNoInputToWorkOrder(@PathVariable(value = "customerCode") String customerCode,
        @PathVariable(value = "warehouseCode") String warehouseCode,
        @PathVariable(value = "companyCode") String companyCode, Model model, ServletRequest request,
        RedirectAttributes redirectAttributes){
        
        StringBuffer orderNoBuffer=new StringBuffer();
        HttpServletRequest httpRequest = null;
        DiskFileItemFactory factory = null;
        ServletFileUpload upload = null;
        List<FileItem> items = null;
        InputStream stream = null;
        try {
            httpRequest = (HttpServletRequest) request;
            httpRequest.setCharacterEncoding("UTF-8");
            factory = new DiskFileItemFactory();
            upload = new ServletFileUpload(factory);
            items = upload.parseRequest(httpRequest);
            Iterator<FileItem> itr = items.iterator();
            log.info("快递单开始导入,商家编码{},仓库编码{},快递公司编码{}",customerCode,warehouseCode,companyCode);
            while (itr.hasNext()) {
                FileItem item = (FileItem) itr.next();
                if (!item.isFormField()) {
                    if (item.getName() != null && !item.getName().equals("")) {
                        List<WorkOrder> workOrders = new ArrayList<WorkOrder>();
                        stream = item.getInputStream();
                        workOrders=analyseExcelToWorkOrder(stream,item.getName(),null);
                        if(workOrders.size()<1){
                            model.addAttribute("message", "没数据或者模板数据异常！");
                            return "expressNoInput/result";
                        }
                        for (WorkOrder workOrder : workOrders) {
                            workOrder.setCustomerCode(customerCode);
                            workOrder.setWarehouseCode(warehouseCode);
                            workOrder.setExpressCompany(companyCode);
                            orderNoBuffer.append("'").append(workOrder.getOrderNo()).append("'").append(",");
                        }
                        int n = workOrderService.saveWorkOrderFromInput(workOrders);
                        Map<String, List<WorkOrder>> myOrders = workOrderService.getInputExceptionOrders(orderNoBuffer.toString(),workOrders);
                        model.addAttribute("normalSize", n);
                        model.addAttribute("exceptionSize", myOrders.get("fail").size());
                        model.addAttribute("failList", myOrders.get("fail"));
                        model.addAttribute("successList", myOrders.get("success"));
                        model.addAttribute("repeatedSize", workOrders.size()-myOrders.get("fail").size()-n);
                        model.addAttribute("allSize", workOrders.size());
                        model.addAttribute("message", "success");
                    } else {
                        model.addAttribute("message", "请提供导入的数据文件！");
                    }
                }
            }
        } catch (Exception e) {
            log.error("exprssNoInputToWorkOrder--Error.",e);
            model.addAttribute("message", "服务器异常，导入数据失败，如果重试还是这样请联系开发技术支持");
        } finally {
            if (null != stream) {
                try {
                    stream.close();
                } catch (IOException e) {
                    log.info("exprssNoInputToWorkOrder--out of memory");
                }
            }
        }
        return "expressNoInput/result";
    }
    
    /**
     * 解析excel文件，保存到作业订单集合中
     * @param 
     * @return 作业订单集合
     * @throws 
     * @author <a href=mailto:libin@nryuncang.com>libin</a>
     * @version 1.0.0
     */
    private List<WorkOrder> analyseExcelToWorkOrder(InputStream stream, String excelName,CustomerLead customerLead)
        throws Exception{
        
        List<WorkOrder> workOrders = new ArrayList<WorkOrder>();
        Workbook rwb = getWorkbook(stream, excelName);
        if (null == rwb)
            return null;
        for (int i = 0; i < rwb.getNumberOfSheets(); i++) {
            Sheet sheet = rwb.getSheetAt(i);
            int rows = sheet.getLastRowNum();
            if (rows > 0) {
                workOrders = ExcelImportUtil.<WorkOrder>getObjectOfExcel(customerLead,sheet,WorkOrder.class,false);
            }
        }
        return workOrders;
    }
    
    /**
     * 根据excel版本初始化 Workbook 对象
     * @param stream 待转化的流
     * @param excelName 文件名称
     * @return 
     * @throws 
     * @author <a href=mailto:libin@nryuncang.com>libin</a>
     * @version 1.0.0
     */
    private Workbook getWorkbook(InputStream stream, String excelName)throws IOException {
        Workbook rwb = null;
        if (excelName.endsWith(".xls")) {
            rwb = new HSSFWorkbook(stream);
        } else if (excelName.endsWith(".xlsx")) {
            rwb = new XSSFWorkbook(stream);
        } else {
            return null;
        }
        return rwb;
    }
}
